package com.lw.test;

/**
 * @author LW
 * @2021/9/24 11:52
 */

import com.lw.pojo.Person;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 分组(partitioningBy/groupingBy)
 * 分区：将stream按条件分为两个Map，比如员工按薪资是否高于8000分为两部分。
 * 分组：将集合分为多个Map，比如员工按性别分组。有单级分组和多级分组。
 */
public class StreamGroup {
    //将员工按薪资是否高于8000分为两部分；将员工按性别和地区分组
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 18,"male", "New York"));
        personList.add(new Person("Jack", 7000, 18,"male", "Washington"));
        personList.add(new Person("Lily", 7800, 18,"female", "Washington"));
        personList.add(new Person("Anni", 8200, 18,"female", "New York"));
        personList.add(new Person("Owen", 9500, 18,"male", "New York"));
        personList.add(new Person("Alisa", 7900, 18,"female", "New York"));

        // 将员工按薪资是否高于8000分组
        Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        // 将员工按性别分组
        Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        // 将员工先按性别分组，再按地区分组
        Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        System.out.println("员工按薪资是否大于8000分组情况：" + part);
        System.out.println("员工按性别分组情况：" + group);
        System.out.println("员工按性别、地区：" + group2);
    }

    //joining可以将stream中的元素用特定的连接符（没有的话，则直接连接）连接成一个字符串。
    @Test
    public void joining() {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

        String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(","));
        System.out.println("所有员工的姓名：" + names);
        List<String> list = Arrays.asList("A", "B", "C");
        String string = list.stream().collect(Collectors.joining("-"));
        System.out.println("拼接后的字符串：" + string);
    }

    //Collectors类提供的reducing方法，相比于stream本身的reduce方法，**增加了对自定义归约的支持。**
    @Test
    public void reducing() {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

        // 每个员工减去起征点后的薪资之和（这个例子并不严谨，但一时没想到好的例子）
        Integer sum = personList.stream().collect(Collectors.reducing(0, Person::getSalary, (i, j) -> (i + j - 5000)));
        System.out.println("员工扣税薪资总和：" + sum);

        // stream的reduce
        Optional<Integer> sum2 = personList.stream().map(Person::getSalary).reduce(Integer::sum);
        System.out.println("员工薪资总和：" + sum2.get());
    }


}
